package com.suoluo.zenadmin.controllers.portal.account;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.paoding.rose.util.Base64;
import net.paoding.rose.web.Invocation;

import com.suoluo.zenadmin.common.StringUtil;
import com.suoluo.zenadmin.vo.account.AccountVO;

public final class LoginManager {

	private static LoginManager instance = new LoginManager();

	private static final String login_key = "com.suoluo.zentravel.login_key";

	private static final String remember_key = "rememberMe";

	private final Base64 base64 = new Base64();

	private LoginManager() {

	}

	public static LoginManager getInstance() {
		return instance;
	}

	public boolean isLogined(Invocation inv) {
		return inv.getRequest().getSession().getAttribute(login_key) != null;
	}

	public boolean isLogined(HttpSession session){
		return session.getAttribute(login_key) != null;
	}
	public void login(Invocation inv, AccountVO loginInfo) {
		HttpSession session = inv.getRequest().getSession();
		session.setAttribute(login_key, loginInfo);
		int accountId = loginInfo.getAccountId();
		String value = base64.encodeToString(int2bytes(accountId));
		saveTo(inv.getRequest(), inv.getResponse(), value);
	}

	public AccountVO getLoginInfo(Invocation inv) {
		HttpSession session = inv.getRequest().getSession();
		return (AccountVO) session.getAttribute(login_key);
	}
	
	public AccountVO getLoginInfo(HttpSession session){
		return (AccountVO) session.getAttribute(login_key);
	}

	private static byte[] int2bytes(int value) {
		byte[] bytes = new byte[4];
		bytes[0] = (byte) (value >> 24);
		bytes[1] = (byte) (value >> 16);
		bytes[2] = (byte) (value >> 8);
		bytes[3] = (byte) (value >> 0);
		return bytes;
	}

	/**
	 * 将4字节的byte数组转成int值
	 * 
	 * @param b
	 * @return
	 */
	public static int bytes2Int(byte[] b) {
		if (b.length != 4) {
			return -1;
		}
		// byte[] a = new byte[4];
		// int i = a.length - 1,j = b.length - 1;
		// for (; i >= 0 ; i--,j--) {//从b的尾部(即int值的低位)开始copy数据
		// if(j >= 0)
		// a[i] = b[j];
		// else
		// a[i] = 0;//如果b.length不足4,则将高位补0
		// }
		// &0xff将byte值无差异转成int,避免Java自动类型提升后,会保留高位的符号位
		int v0 = (b[0] & 0xff) << 24;
		int v1 = (b[1] & 0xff) << 16;
		int v2 = (b[2] & 0xff) << 8;
		int v3 = (b[3] & 0xff);
		return v0 | v1 | v2 | v3;
	}

	public void logout(Invocation inv) {
		HttpSession session = inv.getRequest().getSession();
		session.removeAttribute(login_key);
		// 设置cookie
		removeFrom(inv.getRequest(), inv.getResponse());
	}

	public boolean isRemembered(Invocation inv) {
		String value = readValue(inv.getRequest());
		return !StringUtil.isEmpty(value);
	}

	public Object getRememberInfo(Invocation inv) {
		String value = readValue(inv.getRequest());
		value = ensurePadding(value);
		byte[] content = base64.decodeFromString(value);
		return bytes2Int(content);

	}
	
    private String ensurePadding(String base64)
    {
        int length = base64.length();
        if(length % 4 != 0)
        {
            StringBuilder sb = new StringBuilder(base64);
            for(int i = 0; i < length % 4; i++)
                sb.append('=');

            base64 = sb.toString();
        }
        return base64;
    }

	private void saveTo(HttpServletRequest request,
			HttpServletResponse response, String value) {
		String name = remember_key;
		String comment = null;
		String domain = null;
		String path = calculatePath(request);
		int maxAge = 7 * 24 * 3600;
		int version = 0;
		boolean secure = false;
		boolean httpOnly = true;
		addCookieHeader(response, name, value, comment, domain, path, maxAge,
				version, secure, httpOnly);
	}

	private String calculatePath(HttpServletRequest request) {
		String path = request.getContextPath();
		if (StringUtil.isEmpty(path)) {
			return "/";
		}
		return path;
	}

	private void addCookieHeader(HttpServletResponse response, String name,
			String value, String comment, String domain, String path,
			int maxAge, int version, boolean secure, boolean httpOnly) {
		String headerValue = buildHeaderValue(name, value, comment, domain,
				path, maxAge, version, secure, httpOnly);
		response.addHeader("Set-Cookie", headerValue);
	}

	protected String buildHeaderValue(String name, String value,
			String comment, String domain, String path, int maxAge,
			int version, boolean secure, boolean httpOnly) {
		// if(!StringUtils.hasText(name))
		// throw new IllegalStateException("Cookie name cannot be null/empty.");
		StringBuilder sb = (new StringBuilder(name)).append("=").append(value);
		// if(StringUtils.hasText(value))
		// sb.append(value);
		appendComment(sb, comment);
		appendDomain(sb, domain);
		appendPath(sb, path);
		appendExpires(sb, maxAge);
		appendVersion(sb, version);
		appendSecure(sb, secure);
		appendHttpOnly(sb, httpOnly);
		return sb.toString();
	}

	private void appendComment(StringBuilder sb, String comment) {
		if (!StringUtil.isEmpty(comment)) {
			sb.append("; ");
			sb.append("Comment").append("=").append(comment);
		}
	}

	private void appendDomain(StringBuilder sb, String domain) {
		if (!StringUtil.isEmpty(domain)) {
			sb.append("; ");
			sb.append("Domain").append("=").append(domain);
		}
	}

	private void appendPath(StringBuilder sb, String path) {
		if (!StringUtil.isEmpty(path)) {
			sb.append("; ");
			sb.append("Path").append("=").append(path);
		}
	}

	private void appendExpires(StringBuilder sb, int maxAge) {
		if (maxAge >= 0) {
			sb.append("; ");
			sb.append("Max-Age").append("=").append(maxAge);
			sb.append("; ");
			Date expires;
			if (maxAge == 0) {
				expires = new Date(System.currentTimeMillis() - 86400000L);
			} else {
				Calendar cal = Calendar.getInstance();
				cal.add(13, maxAge);
				expires = cal.getTime();
			}
			String formatted = toCookieDate(expires);
			sb.append("Expires").append("=").append(formatted);
		}
	}

	private void appendVersion(StringBuilder sb, int version) {
		if (version > -1) {
			sb.append("; ");
			sb.append("Version").append("=").append(version);
		}
	}

	private void appendSecure(StringBuilder sb, boolean secure) {
		if (secure) {
			sb.append("; ");
			sb.append("Secure");
		}
	}

	private void appendHttpOnly(StringBuilder sb, boolean httpOnly) {
		if (httpOnly) {
			sb.append("; ");
			sb.append("HttpOnly");
		}
	}

	private static String toCookieDate(Date date) {
		TimeZone tz = TimeZone.getTimeZone("GMT");
		DateFormat fmt = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z",
				Locale.US);
		fmt.setTimeZone(tz);
		return fmt.format(date);
	}

	private void removeFrom(HttpServletRequest request,
			HttpServletResponse response) {
		String name = remember_key;
		String value = "deleteMe";
		String comment = null;
		String domain = null;
		String path = calculatePath(request);
		int maxAge = 0;
		int version = 0;
		boolean secure = false;
		boolean httpOnly = false;
		addCookieHeader(response, name, value, comment, domain, path, maxAge,
				version, secure, httpOnly);
	}

	public String readValue(HttpServletRequest request) {
		String name = remember_key;
		// String value = null;

		Cookie cookies[] = request.getCookies();
		if (cookies != null) {
			for (Cookie c : cookies) {
				if (c.getName().equals(name)) {
					return c.getValue();
				}
			}
			// Cookie arr$[] = cookies;
			// int len$ = arr$.length;
			// for(int i$ = 0; i$ < len$; i$++)
			// {
			// Cookie cookie = arr$[i$];
			// if(cookie.getName().equals(cookieName))
			// return cookie;
			// }

		}
		return null;
		// Cookie cookie = getCookie(request, name);
		// if(cookie != null)
		// {
		// value = cookie.getValue();
		// log.debug("Found '{}' cookie value [{}]", name, value);
		// } else
		// {
		// log.trace("No '{}' cookie value", name);
		// }
		// return value;
	}
	
	public static void main(String []args){
		int id = 10;
		byte [] values = int2bytes(id);
		Base64 base = new Base64();
		String encode = base.encodeToString(values);
		System.out.println(encode);
		values = base.decodeFromString(encode);
		System.out.println(bytes2Int(values));
		
	}

	// private static Cookie getCookie(HttpServletRequest request, String
	// cookieName)
	// {
	//
	// }

	// public static final int DEFAULT_MAX_AGE = -1;
	// public static final int DEFAULT_VERSION = -1;
	// protected static final String NAME_VALUE_DELIMITER = "=";
	// protected static final String ATTRIBUTE_DELIMITER = "; ";
	// protected static final long DAY_MILLIS = 86400000L;
	// protected static final String GMT_TIME_ZONE_ID = "GMT";
	// protected static final String COOKIE_DATE_FORMAT_STRING =
	// "EEE, dd-MMM-yyyy HH:mm:ss z";
	// protected static final String COOKIE_HEADER_NAME = "Set-Cookie";
	// protected static final String PATH_ATTRIBUTE_NAME = "Path";
	// protected static final String EXPIRES_ATTRIBUTE_NAME = "Expires";
	// protected static final String MAXAGE_ATTRIBUTE_NAME = "Max-Age";
	// protected static final String DOMAIN_ATTRIBUTE_NAME = "Domain";
	// protected static final String VERSION_ATTRIBUTE_NAME = "Version";
	// protected static final String COMMENT_ATTRIBUTE_NAME = "Comment";
	// protected static final String SECURE_ATTRIBUTE_NAME = "Secure";
	// protected static final String HTTP_ONLY_ATTRIBUTE_NAME = "HttpOnly";
	// private static final transient Logger log =
	// LoggerFactory.getLogger(org/apache/shiro/web/servlet/SimpleCookie);
	// private String name;
	// private String value;
	// private String comment;
	// private String domain;
	// private String path;
	// private int maxAge;
	// private int version;
	// private boolean secure;
	// private boolean httpOnly;
}
